/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import Sound from '@react-native-oh-tpl/react-native-sound';
import {songs, Track} from '../PlayList/model';
import {DeviceEventEmitter} from 'react-native';

class MusicPlayer {
  private static instance: MusicPlayer | null = null;
  private playlist: Track[] = [];
  private currentTrackIndex: number = 0;
  private soundInstance?: Sound | null = null;
  private isPlaying: boolean = false;
  private progressInterval: NodeJS.Timeout | null = null;
  private onTrackChangeCallback: ((currentTrack: Track) => void) | null = null;
  setOnTrackChange(callback: (currentTrack: Track) => void) {
    this.onTrackChangeCallback = callback;
  }
  private onStatusChangeCallback: ((isPlaying: boolean) => void) | null = null;
  setOnStatusChange(callback: (isPlaying: boolean) => void) {
    this.onStatusChangeCallback = callback;
  }

  constructor() {
    this.playlist = songs;
    this.currentTrackIndex = 0;
    this.loadTrack(this.currentTrackIndex);
  }

  // 静态方法获取实例
  static getInstance() {
    if (!this.instance) {
      this.instance = new MusicPlayer();
    }
    return this.instance;
  }
  private trackCache: Map<number, Sound> = new Map();
  private loadTrack(index: number) {
    if (this.trackCache.has(index)) {
      this.soundInstance = this.trackCache.get(index);
      return;
    }

    if (this.soundInstance) {
      this.soundInstance.release();
    }

    const track = this.playlist[index];
    if (!track) {
      console.warn('Track not found at index', index);
      return;
    }

    this.soundInstance = new Sound(track.fileName, Sound.MAIN_BUNDLE, error => {
      if (error) {
        console.error('Failed to load the track', error);
      }
    });
  }

  play() {
    if (this.soundInstance) {
      this.soundInstance.play(() => {
        this.currentTrackIndex =
          (this.currentTrackIndex + 1) % this.playlist.length;
        this.loadTrack(this.currentTrackIndex);
        DeviceEventEmitter.emit('trackChange', this.getCurrentTrack());
        setTimeout(() => {
          this.play();
          this.isPlaying = true;
          if (this.onStatusChangeCallback) {
            this.onStatusChangeCallback(this.isPlaying);
          }
          if (this.onTrackChangeCallback) {
            this.onTrackChangeCallback(this.getCurrentTrack()!);
          }
        }, 2000);
      });
      this.isPlaying = true;
      if (this.onStatusChangeCallback) {
        this.onStatusChangeCallback(this.isPlaying);
      }
    }
  }

  pause() {
    if (this.soundInstance && this.isPlaying) {
      this.soundInstance.pause();
      this.isPlaying = false;
      if (this.onStatusChangeCallback) {
        this.onStatusChangeCallback(this.isPlaying);
      }
    }
  }

  nextTrack() {
    this.currentTrackIndex =
      (this.currentTrackIndex + 1) % this.playlist.length;
    this.isPlaying = true;
    if (this.onStatusChangeCallback) {
      this.onStatusChangeCallback(this.isPlaying);
    }
    this.loadTrack(this.currentTrackIndex);
    if (this.onTrackChangeCallback) {
      this.onTrackChangeCallback(this.getCurrentTrack()!);
    }
    DeviceEventEmitter.emit('trackChange', this.getCurrentTrack());
    setTimeout(() => {
      this.play();
    }, 2000);
  }

  previousTrack() {
    this.currentTrackIndex =
      (this.currentTrackIndex - 1 + this.playlist.length) %
      this.playlist.length;
    this.isPlaying = true;
    if (this.onStatusChangeCallback) {
      this.onStatusChangeCallback(this.isPlaying);
    }
    this.loadTrack(this.currentTrackIndex);
    if (this.onTrackChangeCallback) {
      this.onTrackChangeCallback(this.getCurrentTrack()!);
    }
    DeviceEventEmitter.emit('trackChange', this.getCurrentTrack());
    setTimeout(() => {
      this.play();
    }, 2000);
  }

  playTrackByIndex(songID: string, isPlaying: boolean) {
    let index = songs.findIndex(item => item.songID == songID);
    if (index < 0 || index >= this.playlist.length) {
      console.warn('Invalid track index:', index);
    }
    this.isPlaying = isPlaying;
    this.currentTrackIndex = index;
    this.loadTrack(index);
    if (this.onStatusChangeCallback) {
      this.onStatusChangeCallback(this.isPlaying);
    }
    if (this.onTrackChangeCallback) {
      this.onTrackChangeCallback(this.getCurrentTrack()!);
    }
    DeviceEventEmitter.emit('trackChange', this.getCurrentTrack());
    setTimeout(() => {
      isPlaying && this.play();
    }, 2000);
  }

  getCurrentStatus() {
    return this.isPlaying;
  }

  getCurrentTrack(): Track | null {
    return this.playlist[this.currentTrackIndex] || null;
  }

  setCurrentTime(value: number) {
    if (this.soundInstance) {
      this.soundInstance.setCurrentTime(value);
    }
  }

  onProgress(callback: (currentTime: number, duration: number) => void) {
    if (!this.soundInstance) {
      return;
    }

    this.clearProgressInterval();
    this.progressInterval = setInterval(() => {
      this.soundInstance?.getCurrentTime(currentTime => {
        const duration = this.soundInstance?.getDuration() || 0;
        callback(currentTime, duration);
      });
    }, 500);
  }

  private clearProgressInterval() {
    if (this.progressInterval) {
      clearInterval(this.progressInterval);
      this.progressInterval = null;
    }
  }

  release() {
    this.onTrackChangeCallback = null;
    this.onStatusChangeCallback = null;
    this.soundInstance?.release();
    this.clearProgressInterval();
  }
}

const musicPlayer = new MusicPlayer();

export default musicPlayer;
